package com.beemans.common.ui.views

import android.annotation.SuppressLint
import android.content.Context
import android.os.CountDownTimer
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.core.widget.NestedScrollView

/**
 * @author tiamosu
 * @date 2021/3/15
 */
open class MyNestedScrollView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : NestedScrollView(context, attrs, defStyleAttr) {

    companion object {
        //静止状态
        const val SCROLL_STATE_IDLE = 1

        //拖动或者惯性滑动状态
        const val SCROLL_STATE_SCROLL = 2
    }

    //判断是否是拖动状态
    private var isDragState = false
    private var currentState = SCROLL_STATE_IDLE

    //这里采用100ms来判断是否已经是静止状态，100ms结束后证明是静止状态
    private var scrollCountTimer: CountDownTimer? = null

    //仅允许子View可滑动，禁止自身滑动
    private var isOnlyChildScroll = false

    //滑动监听
    private var scrollListener: ScrollListener? = null

    fun setScrollListener(scrollListener: ScrollListener) {
        this.scrollListener = scrollListener
    }

    fun setOnlyChildScroll(canScroll: Boolean) {
        isOnlyChildScroll = canScroll
    }

    override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
        if (isOnlyChildScroll) {
            return
        }
        super.onScrollChanged(l, t, oldl, oldt)

        if (scrollListener != null) {
            if (isDragState) {//拖动状态单独处理不再进行滚动状态监测
                return
            }
            //滑动时先取消倒计时，设置滑动状态
            cancelTimer()
            if (currentState != SCROLL_STATE_SCROLL) {
                setScrollState(SCROLL_STATE_SCROLL)
            }
            startTimer()
        }
    }

    override fun scrollTo(x: Int, y: Int) {
        if (isOnlyChildScroll) {
            return
        }
        super.scrollTo(x, y)
    }

    //事件拦截
    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        if (isOnlyChildScroll) {
            return false
        }
        return super.onInterceptTouchEvent(event)
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (isOnlyChildScroll) {
            return false
        }

        if (scrollListener != null) {
            kotlin.runCatching {
                when (event.action) {
                    MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> onTouch(false)
                    MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> onTouch(true)
                }
            }
        }
        return super.onTouchEvent(event)
    }

    private fun onTouch(isDown: Boolean) {
        isDragState = isDown
        //我这里把按下的状态默认为了滚动的状态，当然你也可以分开定义
        if (isDown) {
            cancelTimer()
            setScrollState(SCROLL_STATE_SCROLL)
        } else {
            startTimer()
        }
    }

    private fun setScrollState(newState: Int) {
        currentState = newState
        scrollListener?.onScrollStateChanged(newState)

        if (newState == SCROLL_STATE_IDLE) {
            if (scrollY == 0) {
                scrollListener?.onScrollToStart()
            } else {
                val contentView: View? = getChildAt(0)
                if (contentView != null && contentView.measuredHeight == scrollY + height) {
                    scrollListener?.onScrollToEnd()
                }
            }
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        cancelTimer()
    }

    private fun cancelTimer() {
        scrollCountTimer?.cancel()
    }

    private fun startTimer() {
        if (scrollCountTimer == null) {
            scrollCountTimer = object : CountDownTimer(100, 1) {
                override fun onTick(millisUntilFinished: Long) {}
                override fun onFinish() {
                    setScrollState(SCROLL_STATE_IDLE)
                }
            }
        }
        scrollCountTimer?.start()
    }

    open class DefaultScrollListener : ScrollListener {
        override fun onScrollStateChanged(newState: Int) {
        }

        override fun onScrollToStart() {
        }

        override fun onScrollToEnd() {
        }
    }

    interface ScrollListener {
        //滑动状态回调
        fun onScrollStateChanged(newState: Int)

        //滑动到顶部时的回调
        fun onScrollToStart()

        //滑动到底部时的回调
        fun onScrollToEnd()
    }
}